#include "bsp_misc.h"

int bsp_led_init(void)
{
    LED_GPIO_CLK_ENABLE();
    
    LL_GPIO_SetPinMode(LED_GPIO_PORT, LED_PIN, LL_GPIO_MODE_OUTPUT);
    LL_GPIO_SetPinOutputType(LED_GPIO_PORT, LED_PIN, LL_GPIO_OUTPUT_PUSHPULL);
    LL_GPIO_SetPinSpeed(LED_GPIO_PORT, LED_PIN, LL_GPIO_SPEED_FREQ_LOW);
    LL_GPIO_SetPinPull(LED_GPIO_PORT, LED_PIN, LL_GPIO_PULL_NO);
    LL_GPIO_SetOutputPin(LED_GPIO_PORT, LED_PIN);
    
    return 0;
}

void bsp_led_toggle(void)
{
    LL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN);
}

void bsp_led_write(uint8_t sta)
{
    sta == 0 ? LL_GPIO_ResetOutputPin(LED_GPIO_PORT, LED_PIN) : LL_GPIO_SetOutputPin(LED_GPIO_PORT, LED_PIN);
}

/******************************************************************************************************************************/

bsp_ticktim_cbf_t bsp_tim_cbf = NULL;

// 1kHz 
const uint32_t BSP_TIME_UNIT_FREQ_HZ = 1000U;
const uint16_t BSP_TIMER_RELOAD = 100 - 1;

int bsp_ticktim_init(void)
{
    LL_TIM_InitTypeDef timer_initpara = {0};

    BSP_TIM_CLK_ENABLE();
    LL_TIM_DeInit(BSP_TIM_NBR);

    timer_initpara.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
    timer_initpara.CounterMode = LL_TIM_COUNTERMODE_UP;
    timer_initpara.Prescaler = (SystemCoreClock / (BSP_TIME_UNIT_FREQ_HZ * (BSP_TIMER_RELOAD + 1))) - 1;
    timer_initpara.Autoreload = BSP_TIMER_RELOAD;
    timer_initpara.RepetitionCounter = 0;
    LL_TIM_Init(BSP_TIM_NBR, &timer_initpara);
    LL_TIM_DisableARRPreload(BSP_TIM_NBR);
    
    LL_TIM_EnableIT_UPDATE(BSP_TIM_NBR);

    NVIC_EnableIRQ(BSP_TIM_IRQn);
    NVIC_SetPriority(BSP_TIM_IRQn, 0);
    
    LL_TIM_EnableCounter(BSP_TIM_NBR); 
    
    return 0;
}

void bsp_ticktim_cbf_regist(bsp_ticktim_cbf_t fun) {
    bsp_tim_cbf = fun;
}

void BSP_TIMER_ISR(void) {

    if (bsp_tim_cbf != NULL) {
        bsp_tim_cbf();
    }
    
    LL_TIM_ClearFlag_UPDATE(BSP_TIM_NBR);
}

/******************************************************************************************************************************/

typedef struct {
    uint32_t pin;
    GPIO_TypeDef *port;
} GPIO_CONFIG_T;

GPIO_CONFIG_T key_pins[] = {
    {BSP_KEY1_PIN, BSP_KEY1_PORT},
    {BSP_KEY2_PIN, BSP_KEY2_PORT},
    {BSP_KEY3_PIN, BSP_KEY3_PORT}
};

void bsp_key_init(void)
{
    LL_GPIO_InitTypeDef gpio_para = {0};

    BSP_KEY1_CLK_ENABLE();
    BSP_KEY2_CLK_ENABLE();
    BSP_KEY3_CLK_ENABLE();
    
    for (uint8_t i = 0; i < BSP_KEY_SUM; i++) {
        gpio_para.Pin = key_pins[i].pin;
        gpio_para.Mode = LL_GPIO_MODE_INPUT;
        gpio_para.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        gpio_para.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
        gpio_para.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(key_pins[i].port, &gpio_para);
    }
}

uint8_t bsp_read_key_sta(uint8_t _key) {
    return (uint8_t)LL_GPIO_IsInputPinSet(key_pins[_key].port, key_pins[_key].pin);
}

/******************************************************************************************************************************/

